package cn.chenxing.module.visualization.controller;

import cn.chenxing.domain.outlierdtect.DataNode;
import cn.chenxing.domain.threadlocal.ThreadData;
import cn.chenxing.domain.util.AlertUtil;
import cn.chenxing.module.visualization.service.VisualService;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXComboBox;
import de.felixroske.jfxsupport.FXMLController;
import javafx.concurrent.Worker;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import netscape.javascript.JSObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;

import java.net.URL;
import java.util.Comparator;
import java.util.List;
import java.util.ResourceBundle;

/**
 * @Description 离群点检测可视化控制层
 * @Author maogen.ymg
 * @Date 2020/4/17 15:56
 */
@Lazy
@FXMLController
@Slf4j
public class VisualOutlierController implements Initializable {

    private List<DataNode> outlierDetectList = null;

    private WebEngine webEngine;

    @FXML
    private WebView webView;

    @FXML
    private JFXComboBox<Integer> zoomLevel;

    @FXML
    private JFXComboBox<String> typeList;

    @FXML
    private JFXButton updateButton;

    @Autowired
    private VisualService visualService;

    OutlierData2Js apps2 = new OutlierData2Js();
    /**
     * 须公有
     * */
    @Setter
    public static class OutlierData2Js{

        private String noOutlierJsonLine = null;
        private String isOutlierJson = null;
        private String noOutlierJsonPoint = null;

        public String getNoOutlierJsonLine() {
            return noOutlierJsonLine;
        }

        public String getIsOutlierJson() {
            return isOutlierJson;
        }

        public String getNoOutlierJsonPoint() {
            return noOutlierJsonPoint;
        }

    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // 类型
        typeList.getItems().addAll("线图", "点图");
        typeList.setValue(typeList.getItems().get(0));

        // 缩放级别
        zoomLevel.getItems().addAll(18,17,16,15,14,13,12,11,10,9,8,7,6,5);
        // 获取Engine
        webEngine = webView.getEngine();
        // 获取页面路径
        String mainUrl = getClass().getResource("/html/visualOutlier.html").toExternalForm();
        // 初始化
        webEngine.load(mainUrl);

        // 设置缩放级别
        zoomLevel.setValue(12);

    }

    @FXML
    public void update() {
        if(ThreadData.get().getTrackData() == null) {
            AlertUtil.showWarnAlert("还没有数据哦", "还没导入数据，请选择文件菜单进行导入");
            return;
        }
        if(ThreadData.get().getTrackData().getOutlierDetectList() == null) {
            AlertUtil.showWarnAlert("无法进行可视化", "还未进行离群点检测分析，请先分析");
            return;
        }
        // 重新加载
        webEngine.reload();
        // 传送数据
        transmitData2Js();
        updateButton.setText("更新");
    }

    /**
     * 传送数据给JS
     */
    private void transmitData2Js() {
        // 数据赋值
        outlierDetectList = ThreadData.get().getTrackData().getOutlierDetectList();
        setAppsDataJson();

        webEngine.getLoadWorker().stateProperty().addListener((ov, oldState, newState) -> {
            if (newState == Worker.State.SUCCEEDED) {
                JSObject win = (JSObject) webEngine.executeScript("window");
                // 把对象设置成为js对象
                win.setMember("apps2",apps2);
                // 设置中心点(起始点)
                win.eval(visualService.setStartPoint(ThreadData.get().getTrackData().getOutlierUserId()));
                // 设置缩放级别
                win.eval(visualService.setZoomLevel(zoomLevel.getValue()));
                // 执行操作
                webEngine.executeScript("execute()");
            }
        });
    }

    /**
     * 设置Apps的数据Json
     */
    private void setAppsDataJson() {
        if(outlierDetectList == null) {
            AlertUtil.showErrorAlert("数据读取失败", "离群点检测结果数据读取失败，请检查！");
            return;
        }
        StringBuilder sb1 = new StringBuilder();
        StringBuilder sb2 = new StringBuilder();
        StringBuilder sb3 = new StringBuilder();
        // start
        sb1.append("[");
        sb2.append("[");
        sb3.append("[");
        // [113.09988,32.70335],[112.1269,32.6976]
        boolean isFirst = true;
        DataNode tempDataNode = null;

        // 排个序（画图按顺序来）
        outlierDetectList.sort(Comparator.comparingLong(DataNode::getNodeId));

        for(DataNode dataNode : outlierDetectList) {
            // 是离散点
            if("是".equals(dataNode.getIsOutlierNode())) {
                sb2.append("[").append(dataNode.getLongitude()).append(",")
                        .append(dataNode.getLatitude()).append("],");
            }else {
                sb3.append("[").append(dataNode.getLongitude()).append(",")
                        .append(dataNode.getLatitude()).append("],");
            }

            if(!isFirst) {
                sb1.append("[[").append(tempDataNode.getLongitude()).append(",")
                        .append(tempDataNode.getLatitude()).append("],[")
                        .append(dataNode.getLongitude()).append(",")
                        .append(dataNode.getLatitude()).append("]],");
            }
            tempDataNode = dataNode;

            isFirst = false;

        }

        sb1.deleteCharAt(sb1.length()-1);
        sb2.deleteCharAt(sb2.length()-1);
        sb3.deleteCharAt(sb3.length()-1);
        // end
        sb1.append("]");
        sb2.append("]");
        sb3.append("]");

        // 先进行清空，否则更新时都会加载
        if("线图".equals(typeList.getValue())) {
            apps2.setNoOutlierJsonPoint(null);
            apps2.setNoOutlierJsonLine(sb1.toString());
        }else {
            // 点图
            apps2.setNoOutlierJsonLine(null);
            apps2.setNoOutlierJsonPoint(sb3.toString());
        }
        apps2.setIsOutlierJson(sb2.toString());
    }

}